<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.staticfile.org/vue/3.0.5/vue.global.js"></script>
</head>

<body>
    <div id="app" class="demo">
        <div>
            <!-- set up 函数的基本使用 -->
            <setupdiv :num="info"></setupdiv>
        </div>
    </div>

    <template id="setupdemo">
        <span>
            {{ num.name }}
        </span>
        <!-- 子组件中尝试修改则会报错 -->
        <button @click="my_print">尝试修改名称</button>
    </template>


</body>
<script>

    const setupConfig = {
        template: '#setupdemo',
        // props 属性需要线接收才能在组件中获取
        props: {
            num: {
                type: Object,
                required: false,
                default: {}
            }
        },
        methods: {
            //函数
            my_print() {
                this.num.name = 'xh'
                console.log('学习 setup 函数');
                console.log("isReactive: " + Vue.isReactive(this.num));
                console.log("isReadonly: " + Vue.isReadonly(this.num));
                let numObj= Vue.toRaw(this.num);
                //通过toRaw返回源对象，就可以修改里面的值。
                numObj.name = "hehe";
                console.log(this.num.name);
                console.log(numObj.name);
            }
        },
        // setup函数接收两个参数分别是 props 和 context
        setup(props, context) {
            console.log(props)
        }
    }

    const HelloVueApp = {
        name: 'app',
        components: {
            setupdiv: setupConfig
        },
        methods: {
            //函数
            my_print() {
                this.num.name = 'xh'
                console.log('学习 setup 函数');
                console.log(Vue.isReactive(this.num));
                console.log(Vue.isReadonly(this.num));
            }
        },
        setup() {
            // 当我们使用 reactive 或 ref 定义一些响应式变量并打算传递给子组件时，为了防止变量在子组件中被修改（单向流）
            const num = Vue.reactive({
                name: 'zy',
                age: 22
            })
            // 我们可以使用 readonly api 创建一个响应式对象的劫持 setter 方法的只读代理对象
            const info = Vue.readonly(num)

            // readonly 函数可接收普通对象、ref或 reactive 创建的响应式对象

            /*1. isProxy 函数可以检查对象是否为由 reactive 或 readonly 创建的代理对象，ref 函数创建的是 RefImpl 对象。
              2. isReactive 函数可以检查对象是都由 reactive 创建的响应式代理对象。
              3. isReadonly 函数可以检查一个对象是否为由 readonly 创建的只读代理对象。
              4. toRaw 函数可以返回由 reactive 或 readonly 代理对象的原始对象
              5. shallowReactive 函数可以创建一个浅层代理对象，只有根级别属性是响应式
              6. shallowReadonly 函数可以创建一个浅层只读代理对象，只有根级别属性是只读的
            */
            return {
                num,
                info
            }
        }
    }
    Vue.createApp(HelloVueApp).mount('#app')
</script>

</html>